package com.mhh.selary.backend.api.impl.project;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.mhh.sdk.beans.LoginUserContext;
import com.mhh.sdk.utils.beans.BeanCopyUtils;
import com.mhh.selary.backend.api.project.ISelaryProjectService;
import com.mhh.selary.backend.dao.api.project.ISelaryProjectDao;
import com.mhh.selary.backend.dao.api.project.ISelaryProjectSubgroupDao;
import com.mhh.selary.backend.dao.api.user.ISelaryUserProjectDao;
import com.mhh.selary.backend.dao.entity.project.SelaryProjectEntity;
import com.mhh.selary.backend.dao.entity.project.SelaryProjectSubgroupEntity;
import com.mhh.selary.backend.dao.entity.user.SelaryUserProjectEntity;
import com.mhh.selary.backend.dto.project.GroupNode;
import com.mhh.selary.backend.dto.project.ProjectDTO;
import com.mhh.selary.backend.dto.project.ProjectGroupTreeDTO;
import com.mhh.selary.backend.dto.project.ProjectSaveDTO;
import com.mhh.selary.backend.dto.project.SubGroupSaveDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * SelaryProjectServiceImpl
 *
 * @author 人工智能
 * @date 2020-09-14 15:43:09
 */
@Slf4j
@Service
public class SelaryProjectServiceImpl implements ISelaryProjectService {

    @Autowired
    private ISelaryProjectDao selaryProjectDao;

    @Autowired
    private ISelaryProjectSubgroupDao selaryProjectSubgroupDao;

    @Autowired
    private ISelaryUserProjectDao userProjectDao;

    private static final Long ROOT_PARENT_ID = 0L;

    @Override
    public List<ProjectDTO> findAll() {
        return BeanCopyUtils.copyList(selaryProjectDao.list(), ProjectDTO.class);
    }

    @Override
    public Long saveProject(ProjectSaveDTO dto) {
        SelaryProjectEntity entity = new SelaryProjectEntity();
        entity.setProjectName(dto.getProjectName());
        entity.setProjectScope(dto.getProjectScope());
        if (dto.getId() == null) {
            selaryProjectDao.save(entity);

            SelaryUserProjectEntity userProjectEntity = new SelaryUserProjectEntity();
            userProjectEntity.setUserId(LoginUserContext.get().getUserId());
            userProjectEntity.setProjectId(entity.getId());
            userProjectDao.save(userProjectEntity);
        } else {
            entity.setId(dto.getId());
            selaryProjectDao.updateById(entity);
        }
        return entity.getId();
    }

    @Override
    public void delProject(Long projectId) {
        selaryProjectDao.removeById(projectId);
    }

    @Override
    public Long saveGroup(SubGroupSaveDTO dto) {
        SelaryProjectSubgroupEntity entity = new SelaryProjectSubgroupEntity();
        entity.setGroupName(dto.getGroupName());
        entity.setProjectId(dto.getProjectId());
        entity.setParentId(dto.getParentId());
        if (dto.getId() == null) {
            selaryProjectSubgroupDao.save(entity);
        } else {
            entity.setId(dto.getId());
            selaryProjectSubgroupDao.updateById(entity);
        }
        return entity.getId();
    }

    @Override
    public void delGroup(Long groupId) {
        selaryProjectSubgroupDao.removeById(groupId);
    }

    @Override
    public ProjectGroupTreeDTO groupTree(Long projectId) {
        LambdaQueryWrapper<SelaryProjectSubgroupEntity> queryWrapper = new LambdaQueryWrapper<SelaryProjectSubgroupEntity>()
                .eq(SelaryProjectSubgroupEntity::getProjectId, projectId)
                .orderByAsc(SelaryProjectSubgroupEntity::getParentId);
        List<SelaryProjectSubgroupEntity> groupList = selaryProjectSubgroupDao.list(queryWrapper);
        Map<Long, List<SelaryProjectSubgroupEntity>> groupMap = groupList.stream().collect(Collectors.groupingBy(SelaryProjectSubgroupEntity::getParentId));
        List<GroupNode> nodeList = Lists.newArrayList();
        List<SelaryProjectSubgroupEntity> rootList = groupMap.get(ROOT_PARENT_ID);
        if (CollectionUtils.isNotEmpty(rootList)) {
            rootList.forEach(groupEntity -> {
                GroupNode rootNode = GroupNode.builder()
                        .id(groupEntity.getId())
                        .groupName(groupEntity.getGroupName())
                        .groupCode(groupEntity.getGroupCode())
                        .parentId(groupEntity.getParentId())
                        .build();
                this.groupChildren(groupMap, rootNode);
                nodeList.add(rootNode);
            });
        }
        SelaryProjectEntity projectEntity = selaryProjectDao.getById(projectId);
        GroupNode topNode = this.getTopNode(projectEntity.getProjectName());
        if (CollectionUtils.isNotEmpty(nodeList)) {
            topNode.setChildren(nodeList);
        }
        ProjectGroupTreeDTO groupTreeDTO = new ProjectGroupTreeDTO();
        groupTreeDTO.setNodeList(Lists.newArrayList(topNode));
        return groupTreeDTO;
    }

    @Override
    public List<ProjectDTO> userProjectDropDown() {
        return BeanCopyUtils.copyList(selaryProjectDao.queryByUser(LoginUserContext.get().getUserId()), ProjectDTO.class);
    }

    private GroupNode getTopNode(String projectName) {
        return GroupNode.builder()
                .id(ROOT_PARENT_ID)
                .groupName(projectName)
                .groupCode(null)
                .parentId(null)
                .build();
    }

    /**
     * 构造分组的树形结构数据
     *
     * @param groupMap
     * @param groupNode
     */
    private void groupChildren(Map<Long, List<SelaryProjectSubgroupEntity>> groupMap, GroupNode groupNode) {
        List<SelaryProjectSubgroupEntity> groupList = groupMap.get(groupNode.getId());
        if (CollectionUtils.isNotEmpty(groupList)) {
            groupList.forEach(groupEntity -> {
                GroupNode subNode = GroupNode.builder()
                        .id(groupEntity.getId())
                        .groupName(groupEntity.getGroupName())
                        .groupCode(groupEntity.getGroupCode())
                        .parentId(groupEntity.getParentId())
                        .build();
                if (CollectionUtils.isEmpty(groupNode.getChildren())) {
                    groupNode.setChildren(Lists.newArrayList());
                }
                groupNode.getChildren().add(subNode);
                this.groupChildren(groupMap, subNode);
            });
        }
    }

}
